package cs470.agent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import Code.BZRClient;
import Code.Tank;

public abstract class AbstractAgent {

	protected BZRClient bzrClient;
	private boolean isRunning;
	private List<Tank> tanks;
	
	public AbstractAgent(BZRClient client) {
		this.bzrClient = client;
		setTanks(new ArrayList<Tank>());
		setRunning(false);
		refreshTanks();
	}
	
	protected void refreshTanks() {
		tanks = bzrClient.getTanks();
	}
	
	protected Tank getTank(int tankId) {
		refreshTanks();
		return tanks.get(tankId);
	}
	
	public void add(final Tank tank) {
		getTanks().add(tank);
	}
	
	public void add(final List<Tank> tanks) {
		this.getTanks().addAll(new ArrayList<>(tanks));
	}
	
	
	public abstract void run();

	public void quit() {
		this.setRunning(false);
	}
	
	protected void drive(final double speed) {
		drive(tanks, speed);
	}
	
	private void drive(final List<Tank> tanks, final double speed) {
		for(final Tank tank : tanks) {
			drive(tank, speed);
		}
	}
	
	private void drive(final Tank tank, final double speed) {
		bzrClient.command("speed " + tank.getId() + " " + speed);
	}
	
	protected void stop() {
		stop(tanks);
	}
	
	private void stop(final List<Tank> tanks) {
		for(final Tank tank : tanks) {
			stop(tank);
		}
	}
	
	private void stop(final Tank tank) {
		drive(tank, 0);
	}
	
	protected void turnR(final Tank tank, final double radians) {
		bzrClient.command("angvel " + tank.getId() + " " + radians);
	}
	
	protected void turn(final double d) {
		turn(tanks, d);
	}
	
	private void turn(final List<Tank> tanks, final double d) {
		for(final Tank tank : tanks) {
			turn(tank, d);
		}
	}
	
	private void turn(final Tank tank, final double degrees) {
		double radians = (degrees*(Math.PI/180d)) * 2d;
		turnR(tank, radians);
	}

	protected void shoot() {
		shoot(tanks);
	}
	
	private void shoot(final List<Tank> tanks) {
		for(final Tank tank: tanks) {
			shoot(tank);
		}
	}
	
	private void shoot(final Tank tank) {
		bzrClient.command("shoot " + tank.getId());
	}
	
	protected void pause(final long milliseconds) {
		try {
			TimeUnit.MILLISECONDS.sleep(milliseconds);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

	public boolean isRunning() {
		return isRunning;
	}

	public void setRunning(boolean isRunning) {
		this.isRunning = isRunning;
	}

	public List<Tank> getTanks() {
		return tanks;
	}

	public void setTanks(List<Tank> tanks) {
		this.tanks = tanks;
	}
	
}
